home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / npasswd / part03 < prev    next >
Encoding:
Text File  |  1991-12-19  |  58.0 KB  |  2,232 lines

  1. Newsgroups: comp.sources.unix
  2. From: clyde@emx.utexas.edu (Clyde Hoover)
  3. Subject: v25i076: npasswd - replacement for passwd(1), Part03/03
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: clyde@emx.utexas.edu (Clyde Hoover)
  8. Posting-Number: Volume 25, Issue 76
  9. Archive-Name: npasswd/part03
  10.  
  11. From clyde@emx.utexas.edu Fri Jan 25 12:45:55 1991
  12. Received: from BBN.COM by pineapple.bbn.com id <AA22526@pineapple.bbn.com>; Fri, 25 Jan 91 12:45:27 -0500
  13. Received: from uunet.UU.NET by BBN.COM id aa03197; 25 Jan 91 12:40 EST
  14. Received: from cs.utexas.edu by uunet.uu.net (5.61/1.14) with SMTP 
  15.     id AA17516; Fri, 25 Jan 91 12:39:43 -0500
  16. Received: from emx.utexas.edu by cs.utexas.edu (5.64/1.93) via SMTP
  17.     id AA18063; Fri, 25 Jan 91 11:38:53 -0600
  18. Posted-Date:  25 Jan 91 17:04:17 GMT
  19. Received: by emx.utexas.edu (5.61/1.8)
  20.     id AA09974; Fri, 25 Jan 91 11:04:20 -0600
  21. To: comp-sources-unix@emx.utexas.edu
  22. Path: ut-emx!clyde
  23. From: Head UNIX Hacquer <ut-emx!clyde@emx.utexas.edu>
  24. Newsgroups: comp.sources.unix
  25. Subject: npasswd, a replacement for passwd(1) (part 3 of 3)
  26. Keywords: Password changing program
  27. Message-Id: <43166@ut-emx.uucp>
  28. Date: 25 Jan 91 17:04:17 GMT
  29. Organization: Moose & Squirrel Software
  30. Lines: 2197
  31. Status: R
  32.  
  33.  
  34. Npasswd is a pretty-much-plug-compatable replacement for passwd(1).
  35. This version incorporates a password checking system
  36. that disallows simple-minded passwords.
  37.  
  38. It does exactly ONE thing - change login passwords, though it would
  39. not be too difficult to make it do shells and GECOS stuff also.
  40.  
  41. I have modeled npasswd after passwd(1) from 4.3BSD and SunOS 4.0, but
  42. it does not impliment the options those versions have.
  43. I have also included support for Sys VR3 password aging.
  44.  
  45. This version runs at our site under SunOS 4.X, Ultrix 4.0, UMAX 4.3 and
  46. MORE/BSD.
  47.  
  48. It is also available via anonymous FTP from emx.utexas.edu in the directory
  49. pub/npasswd.
  50.  
  51. --------- cut here ----------
  52. #! /bin/sh
  53. # This is a shell archive.  Remove anything before this line, then unpack
  54. # it by saving it into a file and typing "sh file".  To overwrite existing
  55. # files, type "sh file -c".  You can also feed this as standard input via
  56. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  57. # will see the following message at the end:
  58. #        "End of archive 3 (of 3)."
  59. # Contents:  CHANGE.LOG checkpasswd/util.c npasswd.c pw_yp.c
  60. # Wrapped by clyde@tigger.cc.utexas.edu on Fri Jan 25 10:35:08 1991
  61. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  62. if test -f 'CHANGE.LOG' -a "${1}" != "-c" ; then 
  63.   echo shar: Will not clobber existing file \"'CHANGE.LOG'\"
  64. else
  65. echo shar: Extracting \"'CHANGE.LOG'\" \(9460 characters\)
  66. sed "s/^X//" >'CHANGE.LOG' <<'END_OF_FILE'
  67. X
  68. XSCCS/s.npasswd.1:
  69. X
  70. XD 1.3    90/08/14 14:45:58 clyde    3 2    00016/00006/00053
  71. XDocument -P flag
  72. X
  73. XD 1.2    89/09/21 14:31:45 clyde    2 1    00009/00016/00050
  74. XMisc changes
  75. X
  76. XD 1.1    89/05/18 10:25:49 clyde    1 0    00066/00000/00000
  77. Xdate and time created 89/05/18 10:25:49 by clyde
  78. X
  79. XUsers allowed to make deltas --
  80. X    everyone
  81. X
  82. XFlags --
  83. X    none
  84. X
  85. XDescription --
  86. X    none
  87. X
  88. XSCCS/s.npasswd.c:
  89. X
  90. XD 1.15    90/08/14 14:23:33 clyde    15 14    00099/00026/00471
  91. X1. Include <errno.h>
  92. X2. Add -P option (input via pipe from program).
  93. X3. Use #ifdefs for index() vs. strchr().
  94. X4. Change usage messages.
  95. X5. Don't prompt if input is from a pipe.
  96. X6. Print all status messages to stdout.
  97. X7. Terminate upon password entry/match error if stdin = pipe.
  98. X8. Exit messages to stdout if stdin = pipe.
  99. X9. Use 'cat' if stdin != tty.
  100. X10. Allow stdin to be tty or pipe (pipe only with -P option).
  101. X11. Add fgetpwent().
  102. X12. In putpwent(), type uid/gid as unsigned if UNSIGNED_UID defined.
  103. X
  104. XD 1.14    90/08/07 15:55:18 mic    14 13    00009/00004/00488
  105. XUse getpwuid() to get user id if getlogin() fails.  This can happen if run
  106. Xfrom an rsh or by /bin/login before you are really logged in.
  107. X
  108. XD 1.13    90/06/05 11:07:10 clyde    13 12    00010/00003/00482
  109. XFix problem with overwriting password buffers
  110. X
  111. XD 1.12    90/01/16 16:21:38 clyde    12 11    00001/00001/00484
  112. XFix echo suppression for SunOS 4.0
  113. X
  114. XD 1.11    90/01/12 14:55:09 clyde    11 10    00006/00002/00478
  115. XBuild properly under SunOS 4.0
  116. X
  117. XD 1.10    89/11/15 14:17:19 clyde    10 9    00002/00001/00478
  118. XUpdate some comments
  119. X
  120. XD 1.9    89/11/01 16:21:29 clyde    9 8    00001/00000/00478
  121. XFix messge-of-the-day output
  122. X
  123. XD 1.8    89/09/27 10:27:17 clyde    8 7    00006/00004/00472
  124. XWork around syslogs with missing defines
  125. X
  126. XD 1.7    89/09/26 15:00:52 clyde    7 6    00015/00008/00461
  127. X1. Add 'message of the day' capability.
  128. X2. Change 'help()' to generalized 'motd()' routine.
  129. X
  130. XD 1.6    89/09/22 15:58:07 clyde    6 5    00033/00000/00436
  131. XInsert putpwent() and rename() [under #ifdef control]
  132. X
  133. XD 1.5    89/09/21 17:16:46 clyde    5 4    00004/00004/00432
  134. XChange occurances of 'npasswd' to 'passwd'
  135. X
  136. XD 1.4    89/09/21 17:08:49 clyde    4 3    00005/00004/00431
  137. XMove some stuff to static storage (bug workaround)
  138. X
  139. XD 1.3    89/06/28 14:20:36 clyde    3 2    00004/00000/00431
  140. XPut ifdefs around some configuration defines
  141. X
  142. XD 1.2    89/06/05 13:14:00 clyde    2 1    00056/00000/00375
  143. XAdd getpass() replacement routine (#ifdef XGETPASS)
  144. X
  145. XD 1.1    89/05/18 10:25:50 clyde    1 0    00375/00000/00000
  146. Xdate and time created 89/05/18 10:25:50 by clyde
  147. X
  148. XUsers allowed to make deltas --
  149. X    everyone
  150. X
  151. XFlags --
  152. X    none
  153. X
  154. XDescription --
  155. X    none
  156. X
  157. XSCCS/s.npasswd.cf:
  158. X
  159. XD 1.1    89/05/18 10:25:52 clyde    1 0    00020/00000/00000
  160. Xdate and time created 89/05/18 10:25:52 by clyde
  161. X
  162. XUsers allowed to make deltas --
  163. X    everyone
  164. X
  165. XFlags --
  166. X    none
  167. X
  168. XDescription --
  169. X    none
  170. X
  171. XSCCS/s.npasswd.hf:
  172. X
  173. XD 1.1    89/05/18 10:25:53 clyde    1 0    00005/00000/00000
  174. Xdate and time created 89/05/18 10:25:53 by clyde
  175. X
  176. XUsers allowed to make deltas --
  177. X    everyone
  178. X
  179. XFlags --
  180. X    none
  181. X
  182. XDescription --
  183. X    none
  184. X
  185. XSCCS/s.pw_passwd.c:
  186. X
  187. XD 1.8    90/08/07 16:01:00 root    8 7    00007/00005/00380
  188. XUse getpwuid() to get user id if getlogin() fails.  This can happen if run
  189. Xfrom an rsh or by /bin/login before you are really logged in.
  190. X
  191. XD 1.7    90/07/23 09:37:18 clyde    7 6    00001/00001/00384
  192. XFix pw_compare()
  193. X
  194. XD 1.6    90/06/22 10:39:16 clyde    6 5    00002/00000/00383
  195. XMake password compare rtn deal with null password
  196. X
  197. XD 1.5    89/11/14 17:00:25 clyde    5 4    00005/00002/00378
  198. XDon't remove temp file unless I created it
  199. X
  200. XD 1.4    89/11/01 16:24:47 clyde    4 3    00003/00003/00377
  201. XChange DEBUG file names to './etc_XXXX'
  202. X
  203. XD 1.3    89/10/02 16:53:17 clyde    3 2    00018/00004/00362
  204. X1. Set file names with #define(s).
  205. X2. Set passwd file mode with a #define.
  206. X
  207. XD 1.2    89/09/22 15:57:24 clyde    2 1    00000/00033/00366
  208. XRemove putpwent() [moved to npasswd.c]
  209. X
  210. XD 1.1    89/05/18 10:25:54 clyde    1 0    00399/00000/00000
  211. Xdate and time created 89/05/18 10:25:54 by clyde
  212. X
  213. XUsers allowed to make deltas --
  214. X    everyone
  215. X
  216. XFlags --
  217. X    none
  218. X
  219. XDescription --
  220. X    none
  221. X
  222. XSCCS/s.pw_userinfo.c:
  223. X
  224. XD 1.4    90/08/07 15:56:31 mic    4 3    00008/00002/00248
  225. XUse getpwuid() to get user id if getlogin() fails.  This can happen if run
  226. Xfrom an rsh or by /bin/login before you are really logged in.
  227. X
  228. XD 1.3    90/06/22 10:39:19 clyde    3 2    00002/00000/00248
  229. XMake password compare rtn deal with null password
  230. X
  231. XD 1.2    89/06/05 13:48:30 clyde    2 1    00172/00105/00076
  232. XFirst working version
  233. X
  234. XD 1.1    89/05/18 10:25:56 clyde    1 0    00181/00000/00000
  235. Xdate and time created 89/05/18 10:25:56 by clyde
  236. X
  237. XUsers allowed to make deltas --
  238. X    everyone
  239. X
  240. XFlags --
  241. X    none
  242. X
  243. XDescription --
  244. X    none
  245. X
  246. XSCCS/s.pw_yp.c:
  247. X
  248. XD 1.14    90/08/14 14:27:17 clyde    14 13    00056/00019/00558
  249. X1. Include filename in passwd open error messages.
  250. X2. Password history checking ifdef on PASSWORD_HISTORY.
  251. X3. Ignore passwd entries starting with YP special cookies.
  252. X4. Detect if local password is in adjunct passwd file.
  253. X5. Add newlines to all quit() messages.
  254. X6. Set real uid to effective uid before running YP update script.
  255. X7. Allow su to override YP ypdate script (env YP_UPDATE_PROC).
  256. X
  257. XD 1.13    90/08/07 16:01:01 root    13 12    00007/00005/00570
  258. XUse getpwuid() to get user id if getlogin() fails.  This can happen if run
  259. Xfrom an rsh or by /bin/login before you are really logged in.
  260. X
  261. XD 1.12    90/06/22 10:39:13 clyde    12 11    00002/00000/00573
  262. XMake password compare rtn deal with null password
  263. X
  264. XD 1.11    90/05/29 14:41:29 clyde    11 10    00002/00001/00571
  265. XSet PATH before firing up YP make
  266. X
  267. XD 1.10    90/03/20 14:58:51 clyde    10 9    00003/00001/00569
  268. XMake sure passwd.ptmp is removed if /etc/ptmp create fails
  269. X
  270. XD 1.9    90/03/19 16:34:51 clyde    9 8    00009/00004/00561
  271. XPut secure RPC stuff in #ifdef SECURE_RPC
  272. X
  273. XD 1.8    90/03/19 16:09:27 clyde    8 7    00033/00014/00532
  274. X1. Split code that does locked temp files into routine.
  275. X2. If on YP master, create both "/etc/ptmp" and "PASSWD_FILE.ptmp".
  276. X
  277. XD 1.7    90/03/19 14:50:56 clyde    7 6    00154/00042/00392
  278. X1. Use direct syslog of errors where needed.
  279. X2. Add stub to call password history check.
  280. X3. Always encrypt password with new salt.
  281. X4. Use RPC calls directly for YP password change.
  282. X5. Add error checking and reporting for YP password changes.
  283. X6. Add stub for secure RPC key change.
  284. X7. Rewrite is_yp_master() to call YP routines instead of using ypwhich.
  285. X8. Add -DYPASSWDD_403 define to cope with SunOS 4.0.3 yppasswdd.
  286. X
  287. XD 1.6    89/11/14 17:00:39 clyde    6 5    00005/00002/00429
  288. XDon't remove temp file unless I created it
  289. X
  290. XD 1.5    89/11/01 16:24:41 clyde    5 4    00003/00003/00428
  291. XChange DEBUG file names to './etc_XXXX'
  292. X
  293. XD 1.4    89/10/02 16:52:59 clyde    4 3    00021/00004/00410
  294. X1. Set file names with #define(s).
  295. X2. Set passwd file mode with a #define.
  296. X
  297. XD 1.3    89/09/26 14:59:23 clyde    3 2    00040/00012/00374
  298. X1. Try yppasswd() call multiple times.
  299. X2. Move check for YP change capability from pw_replace() to pw_permission().
  300. X
  301. XD 1.2    89/05/19 11:01:35 clyde    2 1    00005/00001/00381
  302. XInstall PATH for exec of ypwhich
  303. X
  304. XD 1.1    89/05/18 10:25:57 clyde    1 0    00382/00000/00000
  305. Xdate and time created 89/05/18 10:25:57 by clyde
  306. X
  307. XUsers allowed to make deltas --
  308. X    everyone
  309. X
  310. XFlags --
  311. X    none
  312. X
  313. XDescription --
  314. X    none
  315. X
  316. XSCCS/s.version.h:
  317. X
  318. XD 1.5    90/08/14 14:37:26 clyde    5 4    00001/00001/00007
  319. XBump patch level
  320. X
  321. XD 1.4    90/03/19 13:58:10 clyde    4 3    00002/00002/00006
  322. XBump overall version to 1.2
  323. X
  324. XD 1.3    89/11/28 12:32:30 clyde    3 2    00002/00002/00006
  325. XUpdate version stamp
  326. X
  327. XD 1.2    89/09/21 17:25:54 clyde    2 1    00002/00002/00006
  328. XUpdate date info
  329. X
  330. XD 1.1    89/05/18 10:25:59 clyde    1 0    00008/00000/00000
  331. Xdate and time created 89/05/18 10:25:59 by clyde
  332. X
  333. XUsers allowed to make deltas --
  334. X    everyone
  335. X
  336. XFlags --
  337. X    none
  338. X
  339. XDescription --
  340. X    none
  341. X
  342. XSCCS/s.README:
  343. X
  344. XD 1.6    90/03/19 16:36:31 clyde    6 5    00002/00000/00129
  345. XAdd info about defining SECURE_RPC
  346. X
  347. XD 1.5    90/03/19 16:10:58 clyde    5 4    00000/00007/00129
  348. XRemove stuff about YPPASSWDD_403
  349. X
  350. XD 1.4    90/03/19 15:05:05 clyde    4 3    00015/00007/00121
  351. X1. Fix errors.
  352. X2. Explain configuring for SunOS 4.0.3 
  353. X
  354. XD 1.3    89/11/28 12:24:45 clyde    3 2    00038/00004/00090
  355. XAdd sketch about the configuration file
  356. X
  357. XD 1.2    89/10/24 10:48:21 clyde    2 1    00001/00002/00093
  358. XRemove 'beta test' comment
  359. X
  360. XD 1.1    89/05/18 10:26:01 clyde    1 0    00095/00000/00000
  361. Xdate and time created 89/05/18 10:26:01 by clyde
  362. X
  363. XUsers allowed to make deltas --
  364. X    everyone
  365. X
  366. XFlags --
  367. X    none
  368. X
  369. XDescription --
  370. X    none
  371. X
  372. XSCCS/s.npasswd.help:
  373. X
  374. XD 1.1    89/09/21 14:20:53 clyde    1 0    00020/00000/00000
  375. Xdate and time created 89/09/21 14:20:53 by clyde
  376. X
  377. XUsers allowed to make deltas --
  378. X    everyone
  379. X
  380. XFlags --
  381. X    none
  382. X
  383. XDescription --
  384. X    none
  385. X
  386. XSCCS/s.Makefile.dist:
  387. X
  388. XD 1.8    90/07/23 09:59:01 clyde    8 7    00001/00001/00163
  389. XFix error in BSD build options
  390. X
  391. XD 1.7    89/12/05 09:37:18 clyde    7 6    00001/00001/00163
  392. XFix bug in install directives
  393. X
  394. XD 1.6    89/10/30 14:34:11 clyde    6 5    00006/00005/00158
  395. XAdd DEST to install lines to allow install in alternate fs tree
  396. X
  397. XD 1.5    89/10/24 11:17:43 clyde    5 4    00019/00012/00144
  398. X1. Add MANDIR for manual page install.
  399. X2. Change npasswd to $(PASSWD) except for source file references.
  400. X3. Don't replace config and help files if they already exist.
  401. X
  402. XD 1.4    89/10/04 09:54:42 clyde    4 3    00059/00016/00097
  403. XAdd commentary, massive other changes
  404. X
  405. XD 1.3    89/09/27 10:25:28 clyde    3 2    00014/00007/00099
  406. X1. Document  -DXPUTPWENT flag.
  407. X2. Better paramaterization of file names.
  408. X
  409. XD 1.2    89/09/26 15:01:52 clyde    2 1    00007/00005/00099
  410. XAdd message-of-the-day file
  411. X
  412. XD 1.1    89/09/21 17:22:20 clyde    1 0    00104/00000/00000
  413. Xdate and time created 89/09/21 17:22:20 by clyde
  414. X
  415. XUsers allowed to make deltas --
  416. X    everyone
  417. X
  418. XFlags --
  419. X    none
  420. X
  421. XDescription --
  422. X    none
  423. X
  424. XSCCS/s.passwd.1:
  425. X
  426. XD 1.1    89/10/24 10:51:25 clyde    1 0    00056/00000/00000
  427. Xdate and time created 89/10/24 10:51:25 by clyde
  428. X
  429. XUsers allowed to make deltas --
  430. X    everyone
  431. X
  432. XFlags --
  433. X    none
  434. X
  435. XDescription --
  436. X    none
  437. END_OF_FILE
  438. if test 9460 -ne `wc -c <'CHANGE.LOG'`; then
  439.     echo shar: \"'CHANGE.LOG'\" unpacked with wrong size!
  440. fi
  441. # end of 'CHANGE.LOG'
  442. fi
  443. if test -f 'checkpasswd/util.c' -a "${1}" != "-c" ; then 
  444.   echo shar: Will not clobber existing file \"'checkpasswd/util.c'\"
  445. else
  446. echo shar: Extracting \"'checkpasswd/util.c'\" \(11926 characters\)
  447. sed "s/^X//" >'checkpasswd/util.c' <<'END_OF_FILE'
  448. X
  449. X/* --------------------------------------------------------------------  */
  450. X/*                                                                       */
  451. X/*                         Author: Clyde Hoover                          */
  452. X/*                          Computation Center                           */
  453. X/*                   The University of Texas at Austin                   */
  454. X/*                          Austin, Texas 78712                          */
  455. X/*                         clyde@emx.utexas.edu                          */
  456. X/*                   uunet!cs.utexas.edu!ut-emx!clyde                    */
  457. X/*                                                                       */
  458. X/*This code may be distributed freely, provided this notice is retained. */
  459. X/*                                                                       */
  460. X/* --------------------------------------------------------------------  */
  461. X/*
  462. X *    util.c - Miscellanous utility routines
  463. X */
  464. X#ifndef lint
  465. Xstatic char sccsid[] = "@(#)util.c    1.4 11/14/89 (cc.utexas.edu)";
  466. X#endif
  467. X
  468. X#include "checkpasswd.h"
  469. X
  470. X/*
  471. X *    _instring - Compare all sub-strings
  472. X *
  473. X *    Returns:
  474. X *        0 if match not found
  475. X *        rc if match found
  476. X */
  477. X_instring(s1, s2, rc)
  478. Xchar    *s1,        /* String to look for */
  479. X    *s2;        /* String to look for <s1> in */
  480. Xint    rc;        /* What to return on match */
  481. X{
  482. X    int    l;        /* Temp */
  483. X
  484. X    for (l = strlen(s1); *s2; s2++)
  485. X        if (_cistrncmp(s1, s2, l) == 0)
  486. X            return (rc);
  487. X    return(0);
  488. X}
  489. X
  490. X/*
  491. X *    _flipstring - reverse a string in place
  492. X */
  493. X_flipstring(s)
  494. Xchar    *s;        /* String to reverse */
  495. X{
  496. X    char    *p,    /* Scratch */
  497. X        *t;    /* Scratch */
  498. X    char    *malloc();
  499. X
  500. X    t = malloc(strlen(s) + 1);
  501. X    (void) strcpy(t, s);
  502. X    p = t;
  503. X    while (*p) p++;        /* Find end of string */
  504. X    --p;
  505. X    for (; *s; )
  506. X        *s++ = *p--;
  507. X    free(t);
  508. X}
  509. X
  510. X/*
  511. X *    Case indepedant string comparasion routines swiped from
  512. X *    the source to MIT Hesiod.
  513. X *    Since these routines are publicly available,
  514. X *    I presume to redistribute them is not in violation of copyright.
  515. X */
  516. X
  517. X/*
  518. X * Copyright (c) 1986 Regents of the University of California.
  519. X * All rights reserved.  The Berkeley software License Agreement
  520. X * specifies the terms and conditions for redistribution.
  521. X */
  522. X
  523. X/*
  524. X * This array is designed for mapping upper and lower case letter
  525. X * together for a case independent comparison.  The mappings are
  526. X * based upon ascii character sequences.
  527. X */
  528. Xstatic
  529. Xchar charmap[] = {
  530. X    '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  531. X    '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  532. X    '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  533. X    '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  534. X    '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  535. X    '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  536. X    '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  537. X    '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  538. X    '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  539. X    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  540. X    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  541. X    '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  542. X    '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  543. X    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  544. X    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  545. X    '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  546. X    '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  547. X    '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  548. X    '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  549. X    '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  550. X    '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  551. X    '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  552. X    '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  553. X    '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  554. X    '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  555. X    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  556. X    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  557. X    '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
  558. X    '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  559. X    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  560. X    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  561. X    '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  562. X};
  563. X
  564. X/*
  565. X *    cistrcmp - case independant string compare
  566. X */
  567. X_cistrcmp(s1, s2)
  568. Xregister char *s1, *s2;
  569. X{
  570. X    register char *cm = charmap;
  571. X
  572. X    while (cm[*s1] == cm[*s2++])
  573. X        if (*s1++=='\0')
  574. X            return(0);
  575. X    return(cm[*s1] - cm[*--s2]);
  576. X}
  577. X
  578. X/*
  579. X *    cistrncmp - case independant string compare
  580. X */
  581. X_cistrncmp(s1, s2, n)
  582. Xregister char *s1, *s2;
  583. Xregister n;
  584. X{
  585. X    register char *cm = charmap;
  586. X
  587. X    while (--n >= 0 && cm[*s1] == cm[*s2++])
  588. X        if (*s1++ == '\0')
  589. X            return(0);
  590. X    return(n<0 ? 0 : cm[*s1] - cm[*--s2]);
  591. X}
  592. X/* end of UCB copyrighted code     */
  593. X
  594. X/*
  595. X *    _ctran - produce printable version of any ASCII character
  596. X */
  597. Xchar *
  598. X_ctran (c)
  599. Xchar    c;        /* Character to represent */
  600. X{
  601. X    static char    cbuf[8];    /* Return value buffer */
  602. X    char    *p = cbuf;        /* Pointer to cbuf */
  603. X    char    chr = c & 0177;        /* Scratch */
  604. X
  605. X    if (c & 0200) {        /* Meta char - weird but what the hey */
  606. X        *p++ = 'M';
  607. X        *p++ = '-';
  608. X    }
  609. X    if (chr >= ' ' && chr <= '~') {
  610. X        *p++ = chr;
  611. X        *p++ = 0;
  612. X        return (cbuf);
  613. X    }
  614. X    if (chr == 0177)
  615. X        return("DEL");
  616. X    *p++ = '^';
  617. X    *p++ = chr + '@';
  618. X    *p++ = 0;
  619. X    return (cbuf);
  620. X}
  621. X
  622. X/*
  623. X *    The following routines are used by the configuration file processor.
  624. X */
  625. X
  626. X/*
  627. X *    decode_boolean - decode a boolean value
  628. X */
  629. Xstatic
  630. Xdecode_boolean(s)
  631. Xchar    *s;
  632. X{
  633. X    return(*s == '1'
  634. X        | streq(s, "true")
  635. X        | streq(s, "yes")
  636. X        | streq(s, "on"));
  637. X}
  638. X
  639. X/*
  640. X *    decode_int - decode an integer value
  641. X */
  642. Xstatic
  643. Xdecode_int(s)
  644. Xchar    *s;        /* String to decode */
  645. X{
  646. X    int    t;    /* Temp */
  647. X
  648. X    if (xatoi(s, (char *)0, &t))
  649. X        return(t);
  650. X    fprintf(stderr, "Bad numeric value '%s'\n", s);
  651. X    return(-1);
  652. X}
  653. X
  654. X/*
  655. X *    Is argument an octal digit?
  656. X */
  657. Xstatic int    octdigit(c)
  658. Xchar    c;
  659. X{
  660. X    return (c >= '0' && c <= '7');
  661. X}
  662. X
  663. X/*
  664. X *    Is argument a decimal digit?
  665. X */
  666. Xstatic int    decdigit(c)
  667. Xchar    c;
  668. X{
  669. X    return (c >= '0' && c <= '9');
  670. X}
  671. X
  672. X/*
  673. X *    Is argument a hexidecimal digit?
  674. X */
  675. Xstatic int    hexdigit(c)
  676. Xchar    c;
  677. X{
  678. X    return (decdigit(c) |
  679. X        (c >= 'a' &&  c <= 'f') |
  680. X        (c >= 'A' && c <= 'F'));
  681. X}
  682. X
  683. X/*
  684. X *    xatoi - Smart 'atoi' recognizes decimal, octal and hex constants
  685. X */
  686. Xstatic
  687. Xxatoi(ip, ipp, iv)
  688. Xchar    *ip,        /* Pointer to number string */
  689. X    **ipp;        /* Stash pointer to end of string */ /* RETURN VALUE */
  690. Xint    *iv;        /* RETURN VALUE */
  691. X{
  692. X    int    (*func)() = decdigit,    /* Function to check char */
  693. X        base = 10;        /* Conversion base */
  694. X    int    t = 0,            /* Return value */
  695. X        mult = 1;        /* Sign of result */
  696. X    char    *fcc = ip;        /* First char position */
  697. X
  698. X    if (*ip == '-') {        /* Negative number? */
  699. X        ip++;
  700. X        mult = -1;
  701. X    }
  702. X    if (*ip == '0') {     /* Leading '0'? */
  703. X        ip++;
  704. X        if (*ip == 'x' || *ip == 'X') {    /* Hex */
  705. X            base = 16;
  706. X            func = hexdigit;
  707. X            ip++;            /* Skip 'x' */
  708. X        }
  709. X        else {
  710. X            base = 8;        /* Octal */
  711. X            func = octdigit;
  712. X        }
  713. X    }
  714. X    while (*ip && (*func)(*ip)) {
  715. X        t *= base;
  716. X        if (decdigit(*ip))
  717. X            t += (*ip - '0');
  718. X        else
  719. X            t += (*ip >= 'a' ? *ip - 0x57 : *ip - 0x37);
  720. X        ip++;
  721. X    }
  722. X    if (ip == fcc)        /* Nothing processed */
  723. X        return(0);
  724. X    if (ipp)        /* Stash new pointer location */
  725. X        *ipp = ip;
  726. X    *iv = (t * mult);
  727. X    return(1);
  728. X}
  729. X
  730. X/*
  731. X *    decode_string - Copy string, converting backslash escapes
  732. X *    Can handle most of the C backslash escape sequences
  733. X */
  734. Xstatic
  735. Xdecode_string(dst, src, len)
  736. Xchar    *dst,        /* Destination */
  737. X    *src;        /* Source */
  738. Xint    len;
  739. X{
  740. X    int    t;        /* Temp */
  741. X    char    *dstx = dst;    /* Pointer to start of destination */
  742. X    char    quote = 0;    /* Quote character */
  743. X
  744. X    if (*src == '"' || *src == '\'')
  745. X        quote = *src++;
  746. X
  747. X#define    putxchar(P) *dst++ = (P)
  748. X    for (; *src && (dst - dstx) < len; ) {
  749. X        if (*src == '\\') {
  750. X            src++;
  751. X            switch(*src) {
  752. X            case 'a':    putxchar('\007'); src++; break;
  753. X            case 'b':    putxchar('\b'); src++; break;
  754. X            case 'f':    putxchar('\f'); src++; break;
  755. X            case 'n':    putxchar('\n'); src++; break;
  756. X            case 'r':    putxchar('\r'); src++; break;
  757. X            case 't':    putxchar('\t'); src++; break;
  758. X            case '\\':    putxchar('\\'); src++; break;
  759. X            case '0': case '1': case '2': case '3':
  760. X            case '4': case '5': case '6': case '7':
  761. X            case 'x':
  762. X                if (xatoi(src, &src, &t))
  763. X                    putxchar(t & 0xff);
  764. X                break;
  765. X            default:
  766. X                if (quote && *src == quote)
  767. X                    *dst++ = *src++;
  768. X                break;
  769. X            }
  770. X            continue;
  771. X        }
  772. X        else if (*src == '^') {    /* ^C = control-c */
  773. X            src++;
  774. X            if (isupper(*src))
  775. X                putxchar(*src - '@');
  776. X            else if (islower(*src))
  777. X                putxchar(*src - '`');
  778. X            else switch (*src) {
  779. X                 case '[':    putxchar('\033'); break;
  780. X                 case '\\':    putxchar('\034'); break;
  781. X                 case ']':    putxchar('\035'); break;
  782. X                 case '^':    putxchar('\036'); break;
  783. X                 case '-':    putxchar('\037'); break;
  784. X            }
  785. X            src++;
  786. X            continue;
  787. X        }
  788. X        else if (quote && *src == quote)
  789. X            break;
  790. X        *dst++ = *src++;
  791. X    }
  792. X#undef    putxchar
  793. X    *dst = 0;
  794. X}
  795. X
  796. Xstatic char    *default_dicts[] = {    /* List of default dictionaries */
  797. X#ifdef  DEFAULT_DICT
  798. X    DEFAULT_DICT,
  799. X#endif
  800. X    0
  801. X};
  802. X
  803. X/*
  804. X *    readconfig - Read the configuration file 
  805. X *        Returns 1 if success, 0 if not found and -1 if error
  806. X */
  807. Xreadconfig(filename)
  808. Xchar    *filename;
  809. X{
  810. X    char    buf[BUFSIZ];    /* Read buffer */
  811. X    FILE    *fp;        /* File pointer */
  812. X    char    **p;        /* Scratch */
  813. X    int    lineno = 0;    /* Current line number in config file */
  814. X    extern int    standalone;    /* Am I a standalone application? */
  815. X
  816. X    /* "Load" default directories */
  817. X    for (p = default_dicts; *p; p++)
  818. X        add_dict(*p);
  819. X
  820. X    if ((fp = fopen(filename, "r")) == NULL) {
  821. X#ifdef    DEBUG
  822. X        printf("No config file\n");
  823. X#endif
  824. X        return(0);
  825. X    }
  826. X
  827. X    while (fgets(buf, sizeof(buf), fp) != NULL) {
  828. X        char    *key,        /* Key on line */
  829. X            *data;        /* Data on line */
  830. X
  831. X        lineno++;
  832. X        if (buf[0] == '\n')        /* Empty line */
  833. X            continue;
  834. X        if (key = index(buf, '\n'))
  835. X            *key = 0;
  836. X        for (data = buf; *data && *data <= ' '; data++);
  837. X        if (*data == '#')
  838. X            continue;
  839. X        key = data;
  840. X        for (; *data && *data > ' '; data++);    /* Skip to end */
  841. X        if (*data)
  842. X            *data++ = 0;
  843. X        else {
  844. X            if (standalone)
  845. X                printf("\"%s\", line %d: Incomplete line.\n",
  846. X                    filename, lineno);
  847. X            continue;
  848. X        }
  849. X        for (; *data && *data <= ' '; data++);    /* Skip whitespace */
  850. X        if (streq(key, "dictionary"))
  851. X            add_dict(data);
  852. X        else if (streq(key, "singlecase"))
  853. X            single_case = decode_boolean(data);
  854. X        else if (streq(key, "minlength"))
  855. X            min_length = decode_int(data);
  856. X        else if (streq(key, "maxlength"))
  857. X            max_length = decode_int(data);
  858. X        else if (streq(key, "printonly"))
  859. X            print_only = decode_boolean(data);
  860. X        else if (streq(key, "badchars")) {
  861. X            char    xcc[BUFSIZ];
  862. X            char    append = 0;
  863. X
  864. X            if (*data == '+')    /* Add data to existing list */
  865. X                append = *data++;
  866. X            decode_string(xcc, data, BUFSIZ);
  867. X            if (xcc[0] == 0)
  868. X                continue;
  869. X            if (append)
  870. X                (void) strcat(illegalcc, xcc);
  871. X            else
  872. X                (void) strncpy(illegalcc, xcc, sizeof_illegalcc);
  873. X        }
  874. X        else {
  875. X            if (standalone)
  876. X                printf("\"%s\", line %d: Unrecognized keyword '%s'.\n",
  877. X                    filename, lineno, key);
  878. X        }
  879. X    }
  880. X    (void) fclose(fp);
  881. X    return(1);
  882. X}
  883. X
  884. X/*
  885. X *    add_dict - Add a dictionary to the search list
  886. X *
  887. X *    Arguments:
  888. X *        The rest of the line from the configuration file
  889. X *        which contains the path to the dictionary and optionally
  890. X *        a descriptive phrase
  891. X */
  892. Xstatic
  893. Xadd_dict(line)
  894. Xchar    *line;        /* RHS of config line */
  895. X{
  896. X    dictionary    *dx,    /* Tail of directory list */
  897. X            *dn;    /* New entry */
  898. X    char    *tx,        /* Scratch */
  899. X        *p;        /* Scratch */
  900. X    char    *calloc();
  901. X
  902. X#ifdef    DEBUG
  903. X    printf("Add dictionary '%s'\n", line);
  904. X#endif
  905. X    dn = (dictionary *)calloc(sizeof(dictionary), 1);
  906. X    if (dictionaries == 0)
  907. X        dictionaries = dn;
  908. X
  909. X    for (dx = dictionaries; dx->dict_next ; dx = dx->dict_next);
  910. X
  911. X    tx = malloc(strlen(line) + 1);
  912. X    (void) strcpy(tx, line);
  913. X    p = tx;
  914. X    while (*p && *p > ' ') p++;
  915. X    if (*p)
  916. X        *p++ = 0;
  917. X    dn->dict_path = tx;
  918. X    dn->dict_desc = p;
  919. X    dx->dict_next = dn;
  920. X    dn->dict_next = 0;
  921. X}
  922. X/*    End util.c */
  923. END_OF_FILE
  924. if test 11926 -ne `wc -c <'checkpasswd/util.c'`; then
  925.     echo shar: \"'checkpasswd/util.c'\" unpacked with wrong size!
  926. fi
  927. # end of 'checkpasswd/util.c'
  928. fi
  929. if test -f 'npasswd.c' -a "${1}" != "-c" ; then 
  930.   echo shar: Will not clobber existing file \"'npasswd.c'\"
  931. else
  932. echo shar: Extracting \"'npasswd.c'\" \(15199 characters\)
  933. sed "s/^X//" >'npasswd.c' <<'END_OF_FILE'
  934. X
  935. X/* --------------------------------------------------------------------  */
  936. X/*                                                                       */
  937. X/*                         Author: Clyde Hoover                          */
  938. X/*                          Computation Center                           */
  939. X/*                   The University of Texas at Austin                   */
  940. X/*                          Austin, Texas 78712                          */
  941. X/*                         clyde@emx.utexas.edu                          */
  942. X/*                   uunet!cs.utexas.edu!ut-emx!clyde                    */
  943. X/*                                                                       */
  944. X/*This code may be distributed freely, provided this notice is retained. */
  945. X/*                                                                       */
  946. X/* --------------------------------------------------------------------  */
  947. X/*
  948. X *    This program duplicates the manual page behavior of the 4.XBSD
  949. X *    passwd(1) command.  It can be configured for use with a variety
  950. X *    of passwd systems (/etc/passwd, /etc/shadow, databases).
  951. X *
  952. X *    The System V support is untested (by the author - other sites
  953. X *    tell me it works).
  954. X *
  955. X *    Here we have only the most abstract data needed (login name,
  956. X *    user id, current password, new password).
  957. X *    All other information needed (the full password line, etc),
  958. X *    is kept down in the 'method' routines.
  959. X *
  960. X *    The 'method' routines are:
  961. X *
  962. X *    pw_initalize()        Do initializations 
  963. X *    pw_getuserbyname()    Get user information by name
  964. X *    pw_permission()        Check if user has permission
  965. X *                 to change this users' password
  966. X *    pw_compare()        Compare passwords
  967. X *    pw_check()        Check password
  968. X *                 Returns 1 if ok, 0 otherwise
  969. X *    pw_replace()        Replace the password
  970. X *    pw_cleanup()        Cleanup
  971. X */
  972. X#ifdef    SYSLOG
  973. X#include <syslog.h>
  974. X# ifndef    LOG_AUTH
  975. X#  define    LOG_AUTH    0
  976. X# endif
  977. X# ifndef    LOG_CONS
  978. X#  define    LOG_CONS    0
  979. X# endif
  980. X#endif
  981. X
  982. X#include <ctype.h>
  983. X#include <signal.h>
  984. X#include <sys/types.h>
  985. X#include <stdio.h>
  986. X#include <pwd.h>
  987. X#include <errno.h>
  988. X#include "version.h"
  989. X
  990. X#ifndef lint
  991. Xstatic char sccsid[] = "@(#)npasswd.c    1.16 9/24/90 (cc.utexas.edu) /usr/share/src/private/ut/share/bin/passwd/SCCS/s.npasswd.c";
  992. X#endif
  993. X
  994. X#ifndef    CONFIG_FILE
  995. X#define    CONFIG_FILE    "/usr/adm/passwd.conf"
  996. X#endif
  997. X#ifndef    HELP_FILE
  998. X#define    HELP_FILE    "/usr/adm/passwd.help"
  999. X#endif
  1000. X#ifndef    MOTD_FILE
  1001. X#define    MOTD_FILE    "/usr/adm/passwd.motd"
  1002. X#endif
  1003. X
  1004. Xextern int    errno;            /* System error code */
  1005. X
  1006. X#ifdef    sun
  1007. Xstatic char    *options = "alyd:e:F:n:fPsVx:";    /* Command line options */
  1008. X#else
  1009. Xstatic char    *options = "fPsV";    /* Command line options */
  1010. X#endif
  1011. Xstatic int    retries = 3;        /* Retry limit */
  1012. Xstatic int    from_prog = 0;        /* Data source is a program */
  1013. X
  1014. Xstatic char    username[16],    /* Name of user changing password */
  1015. X        password[16];    /* Current password (encrypted) */
  1016. X
  1017. Xchar    pbuf[16],        /* Password read buffer 1 */
  1018. X    pbuf2[16],        /* Password read buffer 2 */
  1019. X    ppbuf[16],        /* Current password */
  1020. X    mylogin[16];        /* My login name (saved) */
  1021. X
  1022. Xchar    *getpass(),
  1023. X    *malloc(),
  1024. X    *ttyname(),
  1025. X    *getlogin();
  1026. X
  1027. X#ifdef    SYSV
  1028. X#define    index    strchr
  1029. X#endif
  1030. Xchar    *index();
  1031. X
  1032. Xint    catchit();        /* Signal catcher */
  1033. X
  1034. X/*
  1035. X *    passwd - change the password for a user.
  1036. X *
  1037. X *    This program impliments the 'passwd' command.
  1038. X */
  1039. Xmain(argc, argv)
  1040. Xint    argc;
  1041. Xchar    *argv[];
  1042. X{
  1043. X    char    *myname, mysavedname[16];/* My login name */
  1044. X    struct passwd *pw;        /* My passwd entry */
  1045. X    int    opt;            /* Option processing temp */
  1046. X    extern char    *optarg;    /* From getopt() */
  1047. X    extern int    optind;        /* From getopt() */
  1048. X
  1049. X    /*
  1050. X     * Handle the 4.3BSD & SunOS 4.0 command line options.
  1051. X     * Defer everything except password change to other programs.
  1052. X     */
  1053. X    while ((opt = getopt(argc, argv, options)) != EOF) {
  1054. X        switch (opt) {
  1055. X#ifdef    sun
  1056. X        /*
  1057. X         * Recognized the SunOS 4.1 switches
  1058. X         * but just say that we don't handle them.
  1059. X         */
  1060. X        case 'a':
  1061. X            printf("Option \"-a\" not supported.\n");
  1062. X            exit(1);
  1063. X        case 'l':
  1064. X            printf("Option \"-l\" not supported.\n");
  1065. X            exit(1);
  1066. X        case 'y':
  1067. X            printf("Option \"-y\" not supported.\n");
  1068. X            exit(1);
  1069. X        case 'd':
  1070. X            printf("Option \"-d\" not supported.\n");
  1071. X            exit(1);
  1072. X        case 'e':
  1073. X            printf("Option \"-e\" not supported.\n");
  1074. X            exit(1);
  1075. X        case 'n':
  1076. X            printf("Option \"-n\" not supported.\n");
  1077. X            exit(1);
  1078. X        case 'x':
  1079. X            printf("Option \"-x\" not supported.\n");
  1080. X            exit(1);
  1081. X        case 'F':
  1082. X            printf("Option \"-F\" not supported.\n");
  1083. X            exit(1);
  1084. X#endif
  1085. X        case 'f':
  1086. X            punt("chfn");
  1087. X            break;
  1088. X        case 's':
  1089. X            punt("chsh");
  1090. X            break;
  1091. X        case 'P':        /* Data source is a program */
  1092. X            if (getuid())
  1093. X                quit(0, "Option \"-P\" reserved for super-user.\n");
  1094. X            from_prog = 1;
  1095. X            break;
  1096. X        case 'V':
  1097. X            printf("%s; patch level %s\n", version, patchlevel);
  1098. X            exit(0);
  1099. X        }
  1100. X    }
  1101. X    bzero(ppbuf, sizeof(ppbuf));
  1102. X#ifndef    DEBUG
  1103. X    if (geteuid())
  1104. X        quit(0,"Permission denied.\n");
  1105. X#endif
  1106. X    checktty();
  1107. X    savetty();
  1108. X    myname = getlogin();
  1109. X    if (myname == 0 || *myname == '\0') {
  1110. X        if ((pw = getpwuid(getuid())) == ((struct passwd *)NULL))
  1111. X            quit(1, "Cannot get your login name.\n");
  1112. X        strncpy(mysavedname, pw->pw_name, sizeof(mysavedname));
  1113. X        myname = mysavedname;
  1114. X    }
  1115. X    (void) strcpy(mylogin, myname);
  1116. X    (void) signal(SIGINT, catchit);
  1117. X    (void) signal(SIGQUIT, catchit);
  1118. X
  1119. X#ifdef    SYSLOG
  1120. X    openlog("passwd", LOG_PID | LOG_CONS, LOG_AUTH);
  1121. X#endif
  1122. X    setcheckpasswd("-c", CONFIG_FILE, 0);
  1123. X    pw_initialize();
  1124. X
  1125. X    if (argv[optind])
  1126. X        (void) strcpy(username, argv[optind]);
  1127. X    else
  1128. X        (void) strcpy(username, mylogin);
  1129. X
  1130. X    if (strcmp(username, mylogin) == 0 && getuid()) {
  1131. X        if (pw_getuserbyname(username, password) == 0)
  1132. X            quit(1, "Cannot get your password information.\n");
  1133. X        if (password[0])
  1134. X            getpassword(password, ppbuf, sizeof(ppbuf));
  1135. X    }
  1136. X    else {
  1137. X        if (pw_getuserbyname(username, password) == 0)
  1138. X            quit(0, "No such user %s\n", argv[optind]);
  1139. X        if (pw_permission() == 0)
  1140. X            quit(0, "Permission denied.\n");
  1141. X        printf("Changing password for %s\n", username);
  1142. X    }
  1143. X    motd(MOTD_FILE, (char *)0);
  1144. X
  1145. X    for (;;) {
  1146. X        char    *px;        /* Temp */
  1147. X        int    ntries = 0;    /* Password match counter */
  1148. X
  1149. X        px = getpass(from_prog ? "" : "New password (? for help): ");
  1150. X        if (px == NULL)
  1151. X            quit(0, "EOF during new password read.\n");
  1152. X        (void) strcpy(pbuf, px);
  1153. X        if (pbuf[0] == '?') {
  1154. X            motd(HELP_FILE, "Missing help file");
  1155. X            continue;
  1156. X        }
  1157. X        /* Sanity check the new password */
  1158. X        if (pw_check(pbuf) == 0)
  1159. X            continue;
  1160. X
  1161. X        /* Get confirmation */
  1162. X        px = getpass(from_prog ? "" : "New password (again): ");
  1163. X        if (px == NULL)
  1164. X            quit(0, "EOF during new password read.\n");
  1165. X        (void) strcpy(pbuf2, px);
  1166. X        if (strcmp(pbuf, pbuf2)) {
  1167. X            if (ntries++ >= retries) 
  1168. X                quit(0, "Too many attempts.\n");
  1169. X            else
  1170. X                printf("They don't match; try again.\n");
  1171. X            if (from_prog)
  1172. X                quit(0, (char *)0);
  1173. X            else
  1174. X                continue;
  1175. X        }
  1176. X        /* Disallow new password == old password */
  1177. X        if (pw_compare(password, pbuf)) {
  1178. X            printf("New password must be different than old; try again.\n");
  1179. X            if (from_prog)
  1180. X                quit(0, (char *)0);
  1181. X            else
  1182. X                continue;
  1183. X        }
  1184. X        else
  1185. X            break;
  1186. X    }
  1187. X    pw_replace(pbuf, ppbuf);
  1188. X#ifdef    SYSLOG
  1189. X    syslog(LOG_INFO, "Password changed for %s by %s\n",
  1190. X        username, mylogin);
  1191. X#endif
  1192. X    printf("Password changed for %s\n", username);
  1193. X    pw_cleanup(0);
  1194. X    exit(0);
  1195. X}
  1196. X
  1197. X
  1198. X/*
  1199. X *    getpassword -- read password and check against current.
  1200. X */
  1201. Xgetpassword(pwd_crypt, pwd_plain, pwlen)
  1202. Xchar    *pwd_crypt,        /* Present password (encrypted) */
  1203. X    *pwd_plain;        /* Present password (plain)  */
  1204. Xint    pwlen;            /* Length of present password buffer */
  1205. X{
  1206. X    int    ntries = 0;    /* Match attempt counter */
  1207. X    char    *px;        /* Temp */
  1208. X
  1209. X    for (;;) {
  1210. X        px = getpass(from_prog ? "" : "Current password: ");
  1211. X        if (px == 0)
  1212. X            quit(0, "EOF during password read.\n");
  1213. X        if (*px == '\0')
  1214. X            continue;
  1215. X        if (!pw_compare(pwd_crypt, px)) {
  1216. X            printf("Password incorrect.\n");
  1217. X            if (ntries++ == retries)
  1218. X                quit(0, "Password not matched.\n");
  1219. X        }
  1220. X        else
  1221. X            break;
  1222. X    }
  1223. X    if (pwd_plain)
  1224. X        (void) strncpy(pwd_plain, px, pwlen);
  1225. X}
  1226. X
  1227. X/* 
  1228. X *    randomstring - create a string of random characters
  1229. X */
  1230. Xrandomstring(buf, len)
  1231. Xchar    buf[];        /* String buffer */
  1232. Xint    len;        /* Length of buf */
  1233. X{
  1234. X    register int    i,        /* Temp */
  1235. X            n;        /* Temp */
  1236. X    time_t        tv;        /* Current time */
  1237. X    char        proto[128];    /* Build buffer */
  1238. X
  1239. X    (void) time (&tv);
  1240. X    /*
  1241. X     * Assumes (implicitly) that sizeof(int) == sizeof(long)
  1242. X     */
  1243. X    (void) srand ( (tv & 0x38d9fcff) ^ getpid ());
  1244. X    for (i = 0; i < sizeof(proto); i++) {    /* fill proto vector */
  1245. X        int    c;        /* Temp */
  1246. X
  1247. X        for (;;) {
  1248. X            c = rand () % 0x7f;    /* turn into ASCII */
  1249. X            if (isalnum (c))
  1250. X                break;
  1251. X        }
  1252. X        proto[i] = (char )c;
  1253. X    }
  1254. X    (void) srand(((unsigned )tv & 0x1a90fefc) ^ getpid());
  1255. X    for (i = 0; i < len; i++) {
  1256. X        n = rand() % sizeof(proto);
  1257. X        buf[i] = proto[n];
  1258. X    }
  1259. X    buf[len] = 0;
  1260. X}
  1261. X
  1262. X/*
  1263. X *    quit - print/log error message and exit
  1264. X */
  1265. Xquit(logit, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  1266. X/*VARARGS2*/
  1267. Xint    logit;        /* 0 = don't log, <> 0 = log message */
  1268. Xchar    *message;    /* Message */
  1269. Xint    *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10;    /* Args */
  1270. X{
  1271. X    if (message) {
  1272. X        /*
  1273. X         * If used from program, direct failure messages to stdout,
  1274. X         * else send to stderr.
  1275. X         */
  1276. X        fprintf(from_prog ? stdout : stderr,  message,
  1277. X            a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  1278. X#ifdef    SYSLOG
  1279. X        if (logit)
  1280. X            syslog(LOG_ERR,  message,
  1281. X                a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  1282. X#endif
  1283. X    }
  1284. X    pw_cleanup(1);
  1285. X    exit(1);
  1286. X}
  1287. X
  1288. X/*
  1289. X *    motd - issue 'message of the day'
  1290. X */
  1291. Xmotd(fn, complaint)
  1292. Xchar    *fn,            /* Name of file to present */
  1293. X    *complaint;        /* Complaint if missing */
  1294. X{
  1295. X    char    cmdbuf[BUFSIZ];        /* Buffer to build command in */
  1296. X
  1297. X    if (access(fn, 0) < 0) {
  1298. X        if (complaint)
  1299. X            printf("%s\n", complaint);
  1300. X        return;
  1301. X    }
  1302. X    if (isatty(0))
  1303. X#ifdef    SYSV
  1304. X        (void) sprintf(cmdbuf, "pg -n -s %s", fn);
  1305. X#else
  1306. X        (void) sprintf(cmdbuf, "more -d %s", fn);
  1307. X#endif
  1308. X    else
  1309. X        (void) sprintf(cmdbuf, "cat %s", fn);
  1310. X
  1311. X    if (fork() == 0) {
  1312. X        (void) setgid(getgid());
  1313. X        (void) setuid(getuid());
  1314. X        (void) system(cmdbuf);
  1315. X        exit(0);
  1316. X    }
  1317. X    (void) wait((int *)0);        /* "Wrong" for BSD, right for SYS V */
  1318. X}
  1319. X
  1320. X/*
  1321. X *    checktty - Attempt to check against being pipe-fed
  1322. X */
  1323. Xchecktty()
  1324. X{
  1325. X    char    *stdin_tty,    /* ttyname(0) */
  1326. X        *stdout_tty,    /* ttyname(1) */
  1327. X        *t;        /* Temp */
  1328. X
  1329. X    if (!isatty(0)) {
  1330. X        if (from_prog == 0)
  1331. X            quit(0, "Input not a tty.\n");
  1332. X        if (lseek(0, 0L, 1) < 0) {
  1333. X            if (errno != ESPIPE)
  1334. X                quit(0, "Input not a tty or pipe.\n");
  1335. X            else
  1336. X                return;
  1337. X        }
  1338. X    }
  1339. X    from_prog = 0;        /* Stdin is a tty - behave normal */
  1340. X    stdin_tty = ttyname(0);
  1341. X    if (stdin_tty == NULL || *stdin_tty == 0)
  1342. X        quit(0, "Cannot get name (stdin).\n");
  1343. X    t = malloc(strlen(stdin_tty) + 1);
  1344. X    if (t == NULL)
  1345. X        quit(1, "Cannot allocate temp memory.");
  1346. X    (void) strcpy(t, stdin_tty);
  1347. X    stdin_tty = t;
  1348. X
  1349. X    stdout_tty = ttyname(1);
  1350. X    if (stdout_tty == NULL || *stdout_tty == 0)
  1351. X        quit(0, "Cannot get name (stdout).\n");
  1352. X    if (strcmp(stdin_tty, stdout_tty))
  1353. X        quit(0, "Input and output are not the same tty.\n");
  1354. X    free(stdin_tty);
  1355. X}
  1356. X
  1357. X/*
  1358. X *    catchit - tty interrupt catcher
  1359. X */
  1360. Xcatchit()
  1361. X{
  1362. X    fixtty();
  1363. X    pw_cleanup(1);
  1364. X    quit(0, "\nInterrupted; changes discarded.\n");
  1365. X}
  1366. X
  1367. X
  1368. X#if    defined(SYSV)
  1369. X#    include <termio.h>        /* Vanilla SV termio */
  1370. X    struct termio saved_tty_mode;
  1371. X#endif
  1372. X
  1373. X#if    defined(SUNOS4)
  1374. X#    include <sys/termios.h>        /* SUN OS 4.0 termio */
  1375. X#define    TCGETA    TCGETS
  1376. X#define    TCSETA    TCSETS
  1377. X    struct termios saved_tty_mode;
  1378. X#endif
  1379. X
  1380. X#if    !defined(SUNOS4) && !defined(SYSV)
  1381. X#    include <sgtty.h>        /* BSD tty */
  1382. X    struct sgttyb saved_tty_mode;
  1383. X    int    saved_local_flags;
  1384. X#endif
  1385. Xchar    saves_valid  = 0;        /* Are the saved values valid? */
  1386. X
  1387. X/*
  1388. X *    savetty - save current terminal settings
  1389. X */
  1390. Xsavetty()
  1391. X{
  1392. X#if    defined(SYSV) || defined(SUNOS4)
  1393. X    (void) ioctl(0, TCGETA, &saved_tty_mode);
  1394. X#else
  1395. X    (void) ioctl(0, TIOCGETP, &saved_tty_mode);
  1396. X    (void) ioctl(0, TIOCLGET, &saved_local_flags);
  1397. X#endif
  1398. X    saves_valid++;
  1399. X}
  1400. X
  1401. X/*
  1402. X *    fixtty - restore saved terminal settings
  1403. X */
  1404. Xfixtty()
  1405. X{
  1406. X    if (saves_valid) {
  1407. X#if    defined(SYSV) || defined(SUNOS4)
  1408. X        (void) ioctl(0, TCSETA, &saved_tty_mode);
  1409. X#else
  1410. X        (void) ioctl(0, TIOCSETP, &saved_tty_mode);
  1411. X        (void) ioctl(0, TIOCLSET, &saved_local_flags);
  1412. X#endif
  1413. X    }
  1414. X}
  1415. X
  1416. X#ifdef    XGETPASS
  1417. X/*
  1418. X *    The system getpass() throws away all but the first 8 characters
  1419. X *    of a password string.  If this isn't enough for you, use this
  1420. X *    routine instead.  This code assumes that stdin is the terminal.
  1421. X */
  1422. Xchar    *
  1423. Xgetpass(prompt)
  1424. Xchar    *prompt;
  1425. X{
  1426. X#if    defined(SYSV)
  1427. X    struct termio    saved,        /* Saved tty characteristics */
  1428. X            noecho;        /* No-echo tty characteristics */
  1429. X    char    *strchr();
  1430. X#endif
  1431. X#if    defined(SUNOS4)
  1432. X    struct termios    saved,        /* Saved tty characteristics */
  1433. X            noecho;        /* No-echo tty characteristics */
  1434. X#else
  1435. X    struct sgttyb    saved,        /* Saved tty characteristics */
  1436. X            noecho;        /* No-echo tty characteristics */
  1437. X#endif
  1438. X    static char    ib[64];        /* Input buffer */
  1439. X    char    *rc;            /* Temp */
  1440. X
  1441. X#if    defined(SYSV) || defined(SUNOS4)
  1442. X    (void) ioctl(0, TCGETA, &saved);
  1443. X    noecho = saved;
  1444. X    noecho.c_lflag &= ~ECHO;
  1445. X    (void) ioctl(0, TCSETA, &noecho);
  1446. X#else
  1447. X    (void) ioctl(0, TIOCGETP, &saved);
  1448. X    noecho = saved;
  1449. X    noecho.sg_flags &= ~ECHO;
  1450. X    (void) ioctl(0, TIOCSETP, &noecho);
  1451. X#endif
  1452. X    fprintf(stderr, "%s", prompt);
  1453. X    fflush(stderr);
  1454. X    rc = fgets(ib, sizeof(ib), stdin);
  1455. X    putc('\n', stderr);
  1456. X    fflush(stderr);
  1457. X
  1458. X#if    defined(SYSV) || defined(SUNOS4)
  1459. X    (void) ioctl(0, TCSETA, &saved);
  1460. X#else
  1461. X    (void) ioctl(0, TIOCSETP, &saved);
  1462. X#endif
  1463. X    if (rc == NULL)
  1464. X        return(NULL);
  1465. X    if (rc = index(ib, '\n'))
  1466. X        *rc = 0;
  1467. X    return(ib);
  1468. X}
  1469. X#endif
  1470. X
  1471. X#ifdef    XPUTPWENT
  1472. X/*
  1473. X *    putpwent - replacement for the System V routine
  1474. X *        This writes the "standard" passwd file format.
  1475. X */
  1476. Xputpwent(p, f)
  1477. Xstruct passwd    *p;    /* Passwd entry to put */
  1478. XFILE    *f;        /* File pointer */
  1479. X{
  1480. X#ifdef    UNSIGNED_UID
  1481. X    fprintf(f, "%s:%s:%u:%u:%s:%s:%s\n",
  1482. X#else
  1483. X    fprintf(f, "%s:%s:%d:%d:%s:%s:%s\n",
  1484. X#endif
  1485. X        p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid,
  1486. X        p->pw_gecos, p->pw_dir, p->pw_shell);
  1487. X}
  1488. X#endif
  1489. X
  1490. X#ifdef    XFGETPWENT
  1491. X/*
  1492. X *    fgetpwent() - read passwd(5) entry from a file
  1493. X *        This reads the "standard" passwd file format.
  1494. X */
  1495. Xstruct passwd *
  1496. Xfgetpwent(f)
  1497. XFILE    *f;            /* Pointer to open passwd format file */
  1498. X{
  1499. X    static struct passwd    pwdata;    /* Return data */
  1500. X    static char    ibuf[BUFSIZ];    /* Input and return data buffer */
  1501. X    char        *p;        /* ACME Pointer Works, Inc */
  1502. X
  1503. X    bzero((char *)&pwdata, sizeof(pwdata));
  1504. X    pwdata.pw_name = pwdata.pw_passwd = pwdata.pw_comment =
  1505. X    pwdata.pw_gecos = pwdata.pw_dir = pwdata.pw_shell = "";
  1506. X
  1507. X    if (fgets(ibuf, sizeof(ibuf), f) == NULL)
  1508. X        return(0);
  1509. X    if ((p = index(ibuf, '\n')) == 0)        /* Zap newline */
  1510. X        quit(1, "Ill-formed passwd entry \"%s\".\n", ibuf);
  1511. X    else
  1512. X        *p = 0;
  1513. X#define    skipc while (*p && *p != ':' && *p != '\n') ++p; if (*p) *p++ = 0
  1514. X    p = ibuf;
  1515. X    pwdata.pw_name = p;    skipc;
  1516. X    pwdata.pw_passwd = p;    skipc;
  1517. X    pwdata.pw_uid = atoi(p); skipc;
  1518. X    pwdata.pw_gid = atoi(p); skipc;
  1519. X    pwdata.pw_gecos = p;    skipc; 
  1520. X    pwdata.pw_dir = p;    skipc;
  1521. X    pwdata.pw_shell = p;
  1522. X    return(&pwdata);
  1523. X#undef    skipc
  1524. X}
  1525. X#endif
  1526. X
  1527. X#ifdef    SYSV
  1528. X/*
  1529. X *    rename - replacement for the 4.2/4.3 BSD rename system call
  1530. X */
  1531. Xrename(src, dst)
  1532. Xchar    *src,        /* Source path */
  1533. X    *dst;        /* Destination path */
  1534. X{
  1535. X    if (unlink(dst) < 0) {
  1536. X        if (errno != ENOENT)
  1537. X            return(-1);
  1538. X    }
  1539. X    if (link(src, dst) < 0)
  1540. X        return(-1);
  1541. X    return(unlink(src));
  1542. X}
  1543. X#endif
  1544. X
  1545. X/*
  1546. X *    punt() - run another program to do what we don't do
  1547. X */
  1548. Xpunt(prog)
  1549. Xchar    *prog;        /* Program to run */
  1550. X{
  1551. X    (void) setgid(getgid());
  1552. X    (void) setuid(getuid());
  1553. X    (void) execlp(prog, prog, 0);
  1554. X    perror(prog);
  1555. X    exit(1);
  1556. X}
  1557. X/*        End npasswd.c        */
  1558. END_OF_FILE
  1559. if test 15199 -ne `wc -c <'npasswd.c'`; then
  1560.     echo shar: \"'npasswd.c'\" unpacked with wrong size!
  1561. fi
  1562. # end of 'npasswd.c'
  1563. fi
  1564. if test -f 'pw_yp.c' -a "${1}" != "-c" ; then 
  1565.   echo shar: Will not clobber existing file \"'pw_yp.c'\"
  1566. else
  1567. echo shar: Extracting \"'pw_yp.c'\" \(16110 characters\)
  1568. sed "s/^X//" >'pw_yp.c' <<'END_OF_FILE'
  1569. X
  1570. X/* --------------------------------------------------------------------  */
  1571. X/*                                                                       */
  1572. X/*                         Author: Clyde Hoover                          */
  1573. X/*                          Computation Center                           */
  1574. X/*                   The University of Texas at Austin                   */
  1575. X/*                          Austin, Texas 78712                          */
  1576. X/*                         clyde@emx.utexas.edu                          */
  1577. X/*                   uunet!cs.utexas.edu!ut-emx!clyde                    */
  1578. X/*                                                                       */
  1579. X/*This code may be distributed freely, provided this notice is retained. */
  1580. X/*                                                                       */
  1581. X/* --------------------------------------------------------------------  */
  1582. X/*
  1583. X *    pw_yp - Routines for dealing with SUN Yellow Pages password files
  1584. X *
  1585. X *    This code can update local password file, can cause rebuilding of
  1586. X *    local YP maps and can use yppasswdd(8) to change YP passwords.
  1587. X *
  1588. X *    Must be linked with -lrpcsvc
  1589. X */
  1590. X#include <stdio.h>
  1591. X#include <sys/param.h>
  1592. X#include <sys/stat.h>
  1593. X#include <signal.h>
  1594. X#include <errno.h>
  1595. X#include <pwd.h>
  1596. X#include <fcntl.h>
  1597. X#include <rpc/rpc.h>
  1598. X#include <rpcsvc/ypclnt.h>
  1599. X#include <rpcsvc/yppasswd.h>
  1600. X#include <sys/socket.h>
  1601. X
  1602. X#ifdef    SECURE_RPC
  1603. X#include <rpc/key_prot.h>
  1604. X#endif
  1605. X
  1606. X#ifdef    SYSV
  1607. X#define    index    strchr
  1608. X#endif
  1609. X
  1610. X#ifdef    SYSLOG
  1611. X#include <syslog.h>
  1612. X#endif
  1613. X
  1614. X#ifndef lint
  1615. Xstatic char sccsid[] = "@(#)pw_yp.c    1.15 1/25/91 (cc.utexas.edu)";
  1616. X#endif
  1617. X
  1618. X#define    NONE    -1    /* YP not active */
  1619. X#define    NOT    0    /* YP active - we are not master */
  1620. X#define    IS    1    /* YP active - we have the password file */
  1621. X
  1622. X#define    SLOP    128    /* Size difference tolerated old <> new passwd file */
  1623. X
  1624. Xtypedef struct passwd    passwd;
  1625. Xtypedef    struct passwd    *passwdp;
  1626. X
  1627. Xstatic passwd    theUser,    /* User being changed */
  1628. X        Me;        /* User invoking passwd */
  1629. Xstatic int    myuid,        /* Uid of invoker */
  1630. X        mytempfile = 0;    /* Does PASSWD_TEMP belong to me? */
  1631. Xstatic char    *ypmaster,    /* Name of the YP master */
  1632. X        *ypdomain;    /* YP domain name */
  1633. X
  1634. X#define    PASSWD_MAP    "passwd.byname"        /* Name of YP passwd map */
  1635. X
  1636. X/*
  1637. X *    File names
  1638. X */
  1639. X#ifndef    PASSWD_FILE
  1640. X#define    PASSWD_FILE    "/etc/passwd"
  1641. X#endif
  1642. X#ifndef    PASSWD_SAVE
  1643. X#define    PASSWD_SAVE    "/etc/opasswd"
  1644. X#endif
  1645. X
  1646. X#ifndef    PASSWD_TEMP
  1647. X#define    PASSWD_TEMP    "/etc/ptmp"
  1648. X#endif
  1649. X
  1650. X#define    PASSWD_MODE    0644
  1651. X#ifdef    DEBUG
  1652. Xstatic char    *passwdtemp = "./etc_ptmp",        /* Temp file */
  1653. X        *passwdfile = "./etc_passwd",        /* Password file */
  1654. X        *savefile = "./etc_opasswd";        /* Save file */
  1655. X#else
  1656. Xstatic char    *passwdtemp = PASSWD_TEMP,
  1657. X        *passwdfile = PASSWD_FILE,
  1658. X        *savefile = PASSWD_SAVE;
  1659. X#endif
  1660. Xstatic char    auxlockfile[MAXPATHLEN];        /* Aux lock file */
  1661. X
  1662. Xextern int    errno;
  1663. X
  1664. Xchar    *getlogin(),
  1665. X    *crypt();
  1666. X
  1667. X/*
  1668. X *    pw_initialize - set up
  1669. X */
  1670. Xpw_initialize()
  1671. X{
  1672. X    passwdp    me;            /* Passwd for invoker */
  1673. X    char    *myname = getlogin();    /* Invoker login name */
  1674. X
  1675. X#ifdef    DEBUG
  1676. X    setpwfile(passwdfile);
  1677. X#endif
  1678. X    myuid = getuid();
  1679. X    if (myname && *myname) {
  1680. X        if ((me = getpwnam(myname)) == NULL)
  1681. X            quit(1, "Cannot get user identification from name.\n");
  1682. X    } else {
  1683. X        if ((me = getpwuid(myuid)) == NULL)
  1684. X            quit(1, "Cannot get user identification from uid.\n");
  1685. X    }
  1686. X
  1687. X    _cppasswd(me, &Me);
  1688. X    return(1);
  1689. X}
  1690. X
  1691. X/*
  1692. X *    pw_getuserbyname - get password
  1693. X *
  1694. X *    Returns 1 if passwd found for <name>
  1695. X *        0 otherwise
  1696. X */
  1697. Xpw_getuserbyname(name, passwdb)
  1698. Xchar    *name,        /* User name */
  1699. X    *passwdb;    /* Where to stuff password */
  1700. X{
  1701. X    passwdp    p;    /* Temp */
  1702. X
  1703. X    if ((p = getpwnam(name)) == NULL)
  1704. X        return(0);
  1705. X    _cppasswd(p, &theUser);
  1706. X    (void) strcpy(passwdb, p->pw_passwd);
  1707. X    return(1);
  1708. X}
  1709. X
  1710. X/*
  1711. X *    pw_permission - check password change permission
  1712. X *
  1713. X *    Returns 1 if password can be changed
  1714. X *        0 if not
  1715. X */
  1716. Xpw_permission()
  1717. X{
  1718. X    /*
  1719. X     * Is this my password or someone elses?
  1720. X     */
  1721. X    if (strcmp(Me.pw_name, theUser.pw_name) && myuid)
  1722. X        return(0);
  1723. X
  1724. X    /*
  1725. X     * If on a YP client, root cannot change another
  1726. X     * users' password via yppasswd(), since we can't
  1727. X     * get a plain text password to pass to yppasswdd().
  1728. X     */
  1729. X    if (myuid == 0 && is_yp_master() == NOT) {
  1730. X        FILE    *pf;
  1731. X        passwdp px,        /* Password file traversal */
  1732. X            fgetpwent();
  1733. X        int    rc = 0;
  1734. X
  1735. X        /* What if passwdfile != /etc/passwd?  */
  1736. X        if ((pf = fopen(passwdfile, "r")) == NULL)
  1737. X            quit(1, "Cannot open password file \"%s\".\n", passwdfile);
  1738. X        /*
  1739. X         * Scan local password file, looking for user
  1740. X         * Cannot use getpwnam() because it will use YP - I want to know
  1741. X         * if the user's password file entry is >>local<<
  1742. X         */
  1743. X        while ((px = fgetpwent(pf)) != NULL) {
  1744. X            if (strcmp(px->pw_name, theUser.pw_name) == 0) {
  1745. X                rc = 1;
  1746. X                break;
  1747. X            }
  1748. X        }
  1749. X        fclose(pf);
  1750. X        if (rc) {
  1751. X            if (strncmp(px->pw_passwd, "##", 2) == 0)
  1752. X                quit(0,
  1753. X                "Changing of adjunct passwords not supported.\n");
  1754. X            return(1);
  1755. X        }
  1756. X        else
  1757. X            quit(0, "Password for %s can only be changed on YP server %s.\n",
  1758. X                theUser.pw_name, ypmaster);
  1759. X    }
  1760. X    /* Check if passwd is '##username' - can't do that yet */
  1761. X
  1762. X    /*
  1763. X     * Other checks can be put here to determine if the invoker should
  1764. X     * be allowed to change this password.
  1765. X     */
  1766. X    return(1);
  1767. X}
  1768. X
  1769. X/*
  1770. X *      pw_compare - compare old and new passwords
  1771. X *
  1772. X *      Returns 1 if check = new, 0 if not
  1773. X */
  1774. Xpw_compare(current, new)
  1775. Xchar    *current,        /* Current pw (encrypted) */
  1776. X    *new;            /* check pw (plain) */
  1777. X{
  1778. X    if (!*current)        /* Is current password null? */
  1779. X        return(0);
  1780. X    /* Put other administrative checks here */
  1781. X    return(!strcmp(current, crypt(new, current)));
  1782. X}
  1783. X
  1784. X/*
  1785. X *      pw_check - sanity check password.  Right now just calls
  1786. X *              the password check code
  1787. X *
  1788. X *      Returns 1 if password is ok to use, 0 otherwise
  1789. X */
  1790. Xpw_check(pwd)
  1791. Xchar    *pwd;
  1792. X{
  1793. X    int    rc = checkpasswd(theUser.pw_uid, pwd);
  1794. X
  1795. X#ifdef    PASSWORD_HISTORY
  1796. X    if (rc)
  1797. X        return(rc);
  1798. X    /* Call password history checker to prevent password reuse */
  1799. X    rc = passwd_history(theUser.pw_uid, pwd);
  1800. X#endif
  1801. X    return(rc);
  1802. X}
  1803. X
  1804. X/*    Error message for when yppasswdd fails with error code 1.  */
  1805. Xstatic char *yperrmsg =
  1806. X"Password change failed: Problem with yppasswdd.\n\n\
  1807. XThis is probably because the YP maps are out of sync\n\
  1808. Xwith the YP passwd file for %s on %s.\n\n\
  1809. XPlease try again later.\n";
  1810. X
  1811. X/*
  1812. X *      pw_replace - replace password in passwd file 
  1813. X */
  1814. Xpw_replace(newpwd, curpwd)
  1815. Xchar    *newpwd,        /* New password (plain) */
  1816. X    *curpwd;        /* Old password (plain) */
  1817. X{
  1818. X    passwdp px,        /* Password file traversal */
  1819. X        fgetpwent();
  1820. X    long    oldsigs,    /* Old signal mask */
  1821. X        blocksigs = sigmask(SIGINT) |    /* Sigs to block */
  1822. X                sigmask(SIGQUIT) |
  1823. X                sigmask(SIGTSTP);
  1824. X    FILE    *tf,        /* New password file output */
  1825. X        *pf;        /* Current password file input */
  1826. X    int    fd,        /* Temp file create fd */
  1827. X        islocal = 0;    /* Is user in local password file */
  1828. X    struct stat    oldstat,    /* Old password file stat */
  1829. X            newstat;    /* New password file stat */
  1830. X
  1831. X    if ((pf = fopen(passwdfile, "r")) == NULL)
  1832. X        quit(1, "Cannot open password file \"%s\".\n", passwdfile);
  1833. X    /*
  1834. X     * Scan local password file, looking for user
  1835. X     * Cannot use getpwnam() because it will use YP - I want to know
  1836. X     * if I have to change a >>local<< password file.
  1837. X     */
  1838. X    while ((px = fgetpwent(pf)) != NULL) {
  1839. X        if (*px->pw_name == '+' || *px->pw_name == '-')
  1840. X            continue;
  1841. X        if (strcmp(px->pw_name, theUser.pw_name) == 0) {
  1842. X            if (strncmp(px->pw_passwd, "##", 2) == 0)
  1843. X                quit(0,
  1844. X                "Changing of adjunct passwords not supported.\n");
  1845. X            islocal++;
  1846. X            break;
  1847. X        }
  1848. X    }
  1849. X    rewind(pf);
  1850. X
  1851. X    /*
  1852. X     * If the user was not in the local password file, use RPC
  1853. X     * to update the Yellow Pages (NIS) password file.
  1854. X     */
  1855. X    if (islocal == 0) {
  1856. X        if (is_yp_master() == NOT) {
  1857. X            int    rc;        /* Return code from ypasswdd */
  1858. X            int    why;        /* RPC call return code */
  1859. X            int    ypport;        /* Port for RPC call */
  1860. X            struct yppasswd yppasswd; /* YP passwd change block */
  1861. X            char    salt[4];    /* Password encryption salt */
  1862. X
  1863. X            if (curpwd[0] == 0)
  1864. X                quit(0, "Cannot change YP password without old password.\n");
  1865. X            randomstring(salt, sizeof(salt));
  1866. X            theUser.pw_passwd = crypt(newpwd, salt);
  1867. X            yppasswd.oldpass = curpwd;
  1868. X            _cppasswd(&theUser, &yppasswd.newpw);
  1869. X#ifdef    DEBUG
  1870. X            printf("yppasswd(%s, %s)\n", curpwd, theUser.pw_passwd);
  1871. X#else
  1872. X            if ((ypport = getrpcport(ypmaster, YPPASSWDPROG,
  1873. X                 YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0)
  1874. X                quit(1, "%s is not running ypassswdd.\n",
  1875. X                     ypmaster);
  1876. X
  1877. X            if (ypport >= IPPORT_RESERVED)
  1878. X                quit(1, "yppasswdd on %s not privleged.\n",
  1879. X                    ypmaster);
  1880. X            rc = callrpc(ypmaster, YPPASSWDPROG, YPPASSWDVERS,
  1881. X                YPPASSWDPROC_UPDATE, xdr_yppasswd, &yppasswd,
  1882. X                xdr_int, &why);
  1883. X
  1884. X            /* RPC call error */
  1885. X            if (rc)
  1886. X#if    NO_CLNT_SPERRNO
  1887. X                clnt_perrno(rc);
  1888. X                quit(1, "Password change failed (%s)\n",
  1889. X                    ypmaster);
  1890. X#else
  1891. X                quit(1, "Password change failed (%s): %s\n",
  1892. X                    ypmaster, clnt_sperrno(rc));
  1893. X#endif
  1894. X
  1895. X            /* Error returned from yppasswdd */
  1896. X            if (why) {
  1897. X#ifdef    SYSLOG
  1898. X                syslog(LOG_ERR,
  1899. X                    "yppasswdd error %d on %s for %s",
  1900. X                    why, ypmaster, theUser.pw_name);
  1901. X#endif
  1902. X                if (why == 1)
  1903. X                   quit(0, yperrmsg,  ypdomain, ypmaster);
  1904. X                else
  1905. X                   quit(1, "Password change failed.\n");
  1906. X            }
  1907. X# ifdef    SECURE_RPC
  1908. X            reset_secret_key(curpwd);
  1909. X# endif /* SECURE_RPC */
  1910. X#endif    /* DEBUG */
  1911. X            return;
  1912. X        }
  1913. X        else    /* User not in local passwd, and not in YP passwd */
  1914. X            quit(1, "User %s missing from password file.\n",
  1915. X                theUser.pw_name);
  1916. X    }
  1917. X
  1918. X    /*
  1919. X     * There is a local password file to change
  1920. X     */
  1921. X    (void) umask(0);
  1922. X    (void) fstat(fileno(pf), &oldstat);
  1923. X    /*
  1924. X     * Use different temp file if on YP master.
  1925. X     * This deals with the SunOS 4.0.3 yppasswdd which creates temp files
  1926. X     * named "passwd-file.ptmp", rather than the traditional "/etc/ptmp".
  1927. X     * But there are still a lot of applications which use /etc/ptmp,
  1928. X     * so is it used as the passwd temp file and the 'auxlockfile' is
  1929. X     * also made --- >>>GROAN<<<.
  1930. X     */
  1931. X    auxlockfile[0] = 0;
  1932. X    if (is_yp_master() == IS) {
  1933. X        (void) sprintf(auxlockfile, "%s.ptmp", passwdfile);
  1934. X        close(mklocktemp(auxlockfile));
  1935. X    }
  1936. X    mytempfile = 1;
  1937. X    fd = mklocktemp(passwdtemp);
  1938. X    if ((tf = fdopen(fd, "w")) == NULL)
  1939. X        quit(1, "Cannot fdopen temp file.\n");
  1940. X
  1941. X    oldsigs = sigblock(blocksigs);
  1942. X    while ((px = fgetpwent(pf)) != NULL) {
  1943. X        if (px->pw_name == 0 || px->pw_name[0] == 0) /* Sanity check */
  1944. X            continue;
  1945. X        if (strcmp(px->pw_name, theUser.pw_name) == 0) {
  1946. X            char    salt[4];    /* Password encryption salt */
  1947. X
  1948. X            randomstring(salt, sizeof(salt));
  1949. X            theUser.pw_passwd = crypt(newpwd, salt);
  1950. X            px = &theUser;
  1951. X        }
  1952. X        (void) putpwent(px, tf);
  1953. X    }
  1954. X    (void) fflush(tf);            /* Force buffers empty */
  1955. X    (void) fstat(fileno(tf), &newstat);    /* Get size */
  1956. X    (void) fclose(tf);
  1957. X    (void) fclose(pf);
  1958. X
  1959. X    /*
  1960. X     * Check if the new password file is complete.  Since the encrypted
  1961. X     * password is of a fixed length, the new file should be roughly
  1962. X     * the same size as the old one.
  1963. X     *
  1964. X     * This assumption will FAIL when this program does chfn and chsh!!! -
  1965. X     * use line counts.
  1966. X     */
  1967. X    if (newstat.st_size < (oldstat.st_size - SLOP))
  1968. X        quit(1,
  1969. X        "New password file appears to be incomplete - aborting.\n");
  1970. X
  1971. X    if (rename(passwdfile, savefile) < 0) {
  1972. X        perror("Password file save");
  1973. X        (void) unlink(passwdtemp);
  1974. X        quit(1, "Can't save password file.\n");
  1975. X    }
  1976. X    if (rename(passwdtemp, passwdfile) < 0) {
  1977. X        perror("Password file replace");
  1978. X        (void) unlink(passwdtemp);
  1979. X        (void) link(savefile, passwdfile);
  1980. X        quit(1, "Can't replace password file.\n");
  1981. X    }
  1982. X    if (is_yp_master() == IS)
  1983. X        updateyp();
  1984. X    (void) sigsetmask(oldsigs);
  1985. X}
  1986. X
  1987. X/*
  1988. X *      pw_cleanup - clean up after myself
  1989. X */
  1990. Xpw_cleanup(code)
  1991. Xint    code;        /* 0 for normal, 1 for abort */ /*NOTUSED*/
  1992. X{
  1993. X    if (mytempfile) {
  1994. X        (void) unlink(passwdtemp);
  1995. X        if (auxlockfile[0])
  1996. X            (void) unlink(auxlockfile);
  1997. X    }
  1998. X}
  1999. X
  2000. X/*
  2001. X *      _newstr - copy string into new storage
  2002. X */
  2003. Xstatic char *
  2004. X_newstr(s)
  2005. Xchar    *s;        /* String to copy */
  2006. X{
  2007. X    register char    *t;    /* Temp */
  2008. X    char    *malloc();
  2009. X
  2010. X    if (s == NULL)
  2011. X        return(0);
  2012. X    t = malloc(strlen(s) + 1);
  2013. X    if (t == NULL)
  2014. X        quit(1, "No memory.\n");
  2015. X    (void) strcpy(t, s);
  2016. X    return(t);
  2017. X}
  2018. X
  2019. X/*
  2020. X *    mklocktemp - Make temp file with exclusive use checking
  2021. X *
  2022. X *    Returns file descriptor of created file, else exits with error
  2023. X */
  2024. Xstatic int
  2025. Xmklocktemp(name)
  2026. Xchar    *name;
  2027. X{
  2028. X    int    fd;
  2029. X
  2030. X    fd = open(name, O_WRONLY|O_CREAT|O_EXCL, PASSWD_MODE);
  2031. X    if (fd < 0) {
  2032. X        if (errno == EEXIST)
  2033. X            quit(0, "Password file busy - try again.\n");
  2034. X        perror("Tempfile create");
  2035. X        quit(1, "Cannot create temp file.\n");
  2036. X    }
  2037. X    return(fd);
  2038. X}
  2039. X
  2040. X/*
  2041. X *     _cppasswd - copy a passwd structure
  2042. X */
  2043. Xstatic
  2044. X_cppasswd(f,t)
  2045. Xpasswdp    f,        /* From */
  2046. X    t;        /* To */
  2047. X{
  2048. X    *t = *f;
  2049. X    t->pw_name = _newstr(f->pw_name);
  2050. X    t->pw_passwd = _newstr(f->pw_passwd);
  2051. X    t->pw_comment = _newstr(f->pw_comment);
  2052. X    t->pw_gecos = _newstr(f->pw_gecos);
  2053. X    t->pw_dir = _newstr(f->pw_dir);
  2054. X    t->pw_shell = _newstr(f->pw_shell);
  2055. X}
  2056. X
  2057. X/*
  2058. X *    is_yp_master - Figure out whether we are running on the Yellow Pages
  2059. X *        master for the password file maps.
  2060. X *
  2061. X *    Returns:
  2062. X *        IS if we are the master
  2063. X *        NOT if we are not the master
  2064. X *        NONE if there is no master
  2065. X */
  2066. X#include <netdb.h>
  2067. X#ifndef    MAXHOSTNAMLEN
  2068. X#define    MAXHOSTNAMLEN 32
  2069. X#endif
  2070. X
  2071. Xis_yp_master()
  2072. X{
  2073. X    static char    known = 0,    /* We've been here */
  2074. X            answer = NOT;    /* ...and this is the answer */
  2075. X    char    hostname[MAXHOSTNAMLEN];    /* Our host name */
  2076. X    char    *index();
  2077. X    struct hostent    *hinfo;
  2078. X
  2079. X    if (known)
  2080. X        return(answer);
  2081. X    (void) gethostname(hostname, sizeof(hostname));
  2082. X    if (yp_get_default_domain(&ypdomain)) {
  2083. X/*         quit(1, "Cannot get YP domain.\n"); */
  2084. X        known++;
  2085. X        return(answer = NONE);        /* Assume no YP running */
  2086. X    }
  2087. X
  2088. X    if (yp_master(ypdomain, PASSWD_MAP, &ypmaster)) {
  2089. X        known++;
  2090. X        return(answer = NONE);        /* Assume no YP running */
  2091. X    }
  2092. X
  2093. X    known++;
  2094. X#ifdef    FASTCHECK
  2095. X    /*
  2096. X     * Stupid (but fast) hostname check (first component only)
  2097. X     */
  2098. X    {
  2099. X        char    *p;            /* Scratch */
  2100. X
  2101. X        if (p = index(ypmaster, '.')) *p = 0;
  2102. X        if (p = index(hostname, '.')) *p = 0;
  2103. X    }
  2104. X#else
  2105. X    /*
  2106. X     * Compare my host name and the YP master's host name.
  2107. X     * Use gethostbyname() to return the fully qualified form so that
  2108. X     * a string compare can be done.
  2109. X     */
  2110. X    if (index(hostname, '.') == 0) {
  2111. X        if ((hinfo = gethostbyname(hostname)) == 0)
  2112. X            quit(1, "Cannot get hostinfo for self.\n");
  2113. X        (void) strcpy(hostname, hinfo->h_name);
  2114. X    }
  2115. X    if (index(ypmaster, '.') == 0) {
  2116. X        static char    ypmaster_f[MAXHOSTNAMLEN];
  2117. X
  2118. X        if ((hinfo = gethostbyname(ypmaster)) == 0)
  2119. X            quit(1, "Cannot get hostinfo for ypmaster.\n");
  2120. X        (void) strcpy(ypmaster_f, hinfo->h_name);
  2121. X        ypmaster = ypmaster_f;
  2122. X    }
  2123. X#endif
  2124. X    if (strcmp(ypmaster, hostname) == 0)
  2125. X        return(answer = IS);
  2126. X    return(answer);
  2127. X}
  2128. X
  2129. X/*
  2130. X *    An example sh(1) script to update YP password map
  2131. X */
  2132. Xchar    *ypcmd =
  2133. X    "(PATH=/bin:/usr/bin; export PATH; ypdirs='/var/yp /etc/yp'\n\
  2134. X    for d in $ypdirs; do\n\
  2135. X        if [ -d $d ]; then\n\
  2136. X            cd $d; exec make passwd\n\
  2137. X        fi\n\
  2138. X    done\n\
  2139. X    echo 'passwd: Cannot rebuild YP maps!' 1>&2\n\
  2140. X    false) >/dev/null &\n";
  2141. X
  2142. X/*
  2143. X *    updateyp - update local YP maps
  2144. X */
  2145. Xupdateyp()
  2146. X{
  2147. X    (void) setuid(geteuid());     /* Get all privs */
  2148. X            /* (This assumes that we are setuid root) */
  2149. X    /*
  2150. X     * This machine is the YP master for passwd - invoke something
  2151. X     * to update the YP maps.
  2152. X     * Super-user can override the default YP updater by setting
  2153. X     * env "YP_UPDATE_PROC" to a command to be run instead.
  2154. X     * The name of the user being changed is piped to stdin of the command.
  2155. X     */
  2156. X    if (myuid == 0) {
  2157. X        char    *getenv();
  2158. X        char    *proc = getenv("YP_UPDATE_PROC");
  2159. X
  2160. X        if (proc && *proc) {
  2161. X            char    cmdbuf[BUFSIZ];
  2162. X
  2163. X            (void) sprintf(cmdbuf, "/bin/echo '%s' | ( %s )",
  2164. X                theUser.pw_name, proc);
  2165. X#ifdef    DEBUG
  2166. X            printf("updateyp (proc): %s", cmdbuf);
  2167. X#endif
  2168. X            (void) system(cmdbuf);
  2169. X            return;
  2170. X        }
  2171. X    }
  2172. X#ifdef    DEBUG
  2173. X    printf("updateyp: %s", ypcmd);
  2174. X#endif
  2175. X    (void) system(ypcmd);
  2176. X}
  2177. X
  2178. X#ifdef    SECURE_RPC
  2179. X/*
  2180. X *    reset_secret_key - Reset secret key for secure RPC
  2181. X */
  2182. Xreset_secret_key(curpwd)
  2183. Xchar    *curpwd;
  2184. X{
  2185. X    char    mynet[MAXNETNAMELEN+1],
  2186. X        key[HEXKEYBYTES+1];
  2187. X
  2188. X    getnetname(mynet);
  2189. X    if (!getsecretkey(mynet, key, curpwd))
  2190. X        return;        /* Secure RPC not running */
  2191. X    if (key[0] = 0)
  2192. X        return;        /* No secret key */
  2193. X    fprintf(stderr, "Cannot change secure RPC key\n");
  2194. X    /*
  2195. X     * Actually I could, but I'd have to steal from Sun source
  2196. X     * code to do it.  Sun wouldn't like that very much, so I won't.
  2197. X     */
  2198. X}
  2199. X#endif
  2200. X/*        End pw_yp.c         */
  2201. END_OF_FILE
  2202. if test 16110 -ne `wc -c <'pw_yp.c'`; then
  2203.     echo shar: \"'pw_yp.c'\" unpacked with wrong size!
  2204. fi
  2205. # end of 'pw_yp.c'
  2206. fi
  2207. echo shar: End of archive 3 \(of 3\).
  2208. cp /dev/null ark3isdone
  2209. MISSING=""
  2210. for I in 1 2 3 ; do
  2211.     if test ! -f ark${I}isdone ; then
  2212.     MISSING="${MISSING} ${I}"
  2213.     fi
  2214. done
  2215. if test "${MISSING}" = "" ; then
  2216.     echo You have unpacked all 3 archives.
  2217.     rm -f ark[1-9]isdone
  2218. else
  2219.     echo You still need to unpack the following archives:
  2220.     echo "        " ${MISSING}
  2221. fi
  2222. ##  End of shell archive.
  2223. exit 0
  2224. -- 
  2225. Clyde Hoover (Shouter-To-Dead-Parrots)    |
  2226. UNIX/VMS Services            | "Any sufficently advanced technology 
  2227. Compuatation Center, UT Austin         | is indisguishable from a rigged demo."
  2228. clyde@emx.utexas.edu            |
  2229.  
  2230.